// $Id: RijndaelProperties.java,v 1.1 2008/08/26 02:10:35 zfh Exp $
//
// $Log: RijndaelProperties.java,v $
// Revision 1.1 2008/08/26 02:10:35 zfh
// *** empty log message ***
//
// Revision 1.1 2007/12/05 09:33:09 ww
// *** empty log message ***
//
// Revision 1.1 2001/05/21 02:24:30 jis
// First version
//
// Revision 1.0 1998/04/07 raif
// + original version.
//
// $Endlog$
/*
 * Copyright (c) 1997, 1998 Systemics Ltd on behalf of the Cryptix Development Team. All rights reserved.
 */
package org.cfw.common.util.aes;

import java.io.InputStream;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.util.Enumeration;
import java.util.Properties;

/**
 * This class acts as a central repository for an algorithm specific properties. It reads an (algorithm).properties file
 * containing algorithm- specific properties. When using the AES-Kit, this (algorithm).properties file is located in the
 * (algorithm).jar file produced by the "jarit" batch/ script command.
 * <p>
 * <b>Copyright</b> &copy; 1997, 1998 <a href="http://www.systemics.com/">Systemics Ltd</a> on behalf of the <a
 * href="http://www.systemics.com/docs/cryptix/">Cryptix Development Team</a>. <br>
 * All rights reserved.
 * <p>
 * <b>$Revision: 1.1 $</b>
 * 
 * @author David Hopwood
 * @author Jill Baker
 * @author Raif S. Naffah
 */
public class RijndaelProperties {// implicit no-argument constructor

    // Constants and variables with relevant static code
    // ...........................................................................

    static final boolean            GLOBAL_DEBUG       = false;

    static final String             ALGORITHM          = "Rijndael";

    static final double             VERSION            = 0.1;

    static final String             FULL_NAME          = ALGORITHM + " ver. " + VERSION;

    static final String             NAME               = "Rijndael_Properties";

    static final Properties         PROPERTIES         = new Properties();

    /** Default properties in case .properties file was not found. */
    private static final String[][] DEFAULT_PROPERTIES = { { "Trace.Rijndael_Algorithm", "true" },
            { "Debug.Level.*", "1" }, { "Debug.Level.Rijndael_Algorithm", "9" }, };

    static {
        if (GLOBAL_DEBUG) System.err.println(">>> " + NAME + ": Looking for " + ALGORITHM + " properties");
        String it = ALGORITHM + ".properties";
        InputStream is = RijndaelProperties.class.getResourceAsStream(it);
        boolean ok = is != null;
        if (ok) try {
            PROPERTIES.load(is);
            is.close();
            if (GLOBAL_DEBUG) System.err.println(">>> " + NAME + ": Properties file loaded OK...");
        } catch (Exception x) {
            ok = false;
        }
        if (!ok) {
            if (GLOBAL_DEBUG) System.err.println(">>> " + NAME + ": WARNING: Unable to load \"" + it
                                                 + "\" from CLASSPATH.");
            if (GLOBAL_DEBUG) System.err.println(">>> " + NAME + ":          Will use default values instead...");
            int n = DEFAULT_PROPERTIES.length;
            for (int i = 0; i < n; i++)
                PROPERTIES.put(DEFAULT_PROPERTIES[i][0], DEFAULT_PROPERTIES[i][1]);
            if (GLOBAL_DEBUG) System.err.println(">>> " + NAME + ": Default PROPERTIES now set...");
        }
    }

    // Properties methods (excluding load and save, which are deliberately not
    // supported).
    // ...........................................................................

    /** Get the value of a property for this algorithm. */
    public static String getProperty(String key) {
        return PROPERTIES.getProperty(key);
    }

    /**
     * Get the value of a property for this algorithm, or return <i>value</i> if the property was not set.
     */
    public static String getProperty(String key, String value) {
        return PROPERTIES.getProperty(key, value);
    }

    /** List algorithm properties to the PrintStream <i>out</i>. */
    public static void list(PrintStream out) {
        list(new PrintWriter(out, true));
    }

    /** List algorithm properties to the PrintWriter <i>out</i>. */
    public static void list(PrintWriter out) {
        out.println("#");
        out.println("# ----- Begin " + ALGORITHM + " PROPERTIES -----");
        out.println("#");
        String key, value;
        Enumeration e = PROPERTIES.propertyNames();
        while (e.hasMoreElements()) {
            key = (String) e.nextElement();
            value = getProperty(key);
            out.println(key + " = " + value);
        }
        out.println("#");
        out.println("# ----- End " + ALGORITHM + " properties -----");
    }

    // public synchronized void load(InputStream in) throws IOException {}

    public static Enumeration propertyNames() {
        return PROPERTIES.propertyNames();
    }

    // public void save (OutputStream os, String comment) {}

    // Developer support: Tracing and debugging enquiry methods
    // (package-private)
    // ...........................................................................

    /**
     * Return true if tracing is requested for a given class.
     * <p>
     * User indicates this by setting the tracing <code>boolean</code> property for <i>label</i> in the
     * <code>(algorithm).properties</code> file. The property's key is "<code>Trace.<i>label</i></code>".
     * <p>
     * 
     * @param label The name of a class.
     * @return True iff a boolean true value is set for a property with the key <code>Trace.<i>label</i></code>.
     */
    static boolean isTraceable(String label) {
        String s = getProperty("Trace." + label);
        if (s == null) return false;
        return new Boolean(s).booleanValue();
    }

    /**
     * Return the debug level for a given class.
     * <p>
     * User indicates this by setting the numeric property with key "<code>Debug.Level.<i>label</i></code>".
     * <p>
     * If this property is not set, "<code>Debug.Level.*</code>" is looked up next. If neither property is set, or if
     * the first property found is not a valid decimal integer, then this method returns 0.
     * 
     * @param label The name of a class.
     * @return The required debugging level for the designated class.
     */
    static int getLevel(String label) {
        String s = getProperty("Debug.Level." + label);
        if (s == null) {
            s = getProperty("Debug.Level.*");
            if (s == null) return 0;
        }
        try {
            return Integer.parseInt(s);
        } catch (NumberFormatException e) {
            return 0;
        }
    }

    /**
     * Return the PrintWriter to which tracing and debugging output is to be sent.
     * <p>
     * User indicates this by setting the property with key <code>Output</code> to the literal <code>out</code> or
     * <code>err</code>.
     * <p>
     * By default or if the set value is not allowed, <code>System.err</code> will be used.
     */
    static PrintWriter getOutput() {
        PrintWriter pw;
        String name = getProperty("Output");
        if (name != null && name.equals("out")) pw = new PrintWriter(System.out, true);
        else pw = new PrintWriter(System.err, true);
        return pw;
    }
}
